package pers.vic.boot.security.data.interceptor;

import org.apache.ibatis.mapping.BoundSql;
import pers.vic.boot.security.data.enums.RowDataHandlerType;
import pers.vic.boot.security.data.model.DataRowAuthColumn;
import pers.vic.boot.security.data.model.DataRowAuthModel;
import pers.vic.boot.security.jwt.AuthorityInfo;

import java.lang.reflect.Field;

/**
 *
 *  @description: 数据权限拦截器的基类
 *  @author Vic.xu
 *  @date: 2020年5月18日下午4:41:27
 */
public abstract class BaseAuthorityMethod {

    /**
     * 当前线程中需要拦截的权限字段数据
     */
    protected static final ThreadLocal<DataRowAuthModel> LOCAL_AUTHORITY_DATA = new ThreadLocal<DataRowAuthModel>();

    /**
     * 当前线程中保存的用户权限信息AuthorityInfo
     */
    protected static final ThreadLocal<AuthorityInfo> LOCAL_AUTHORITY_INFO = new ThreadLocal<AuthorityInfo>();

    /**
     * 设置权限相关数据: 理应在jwtFilter#login的时候
     * @param into
     */
    public static void setAuthrityInfo(AuthorityInfo into) {
        LOCAL_AUTHORITY_INFO.set(into);
    }

    /**
     * 用于权限拦截的时候使用
     * @return
     */
    public static AuthorityInfo getAuthrityInfo() {
        return LOCAL_AUTHORITY_INFO.get();
    }

    /**
     * 清除线程中的用户权限信息,注意主动调用
     * @param into
     */
    public static void removeAuthrityInfo(AuthorityInfo into) {
        LOCAL_AUTHORITY_INFO.remove();
    }

    /**
     * 设置 AuthorityData 参数
     *
     * @param AuthorityData
     */
    protected static void setLocalAuthorityData(DataRowAuthModel authorityData) {
        LOCAL_AUTHORITY_DATA.set(authorityData);
    }

    /**
     * 获取 AuthorityData 参数
     *
     * @return
     */
    public static DataRowAuthModel getLocalAuthorityData() {
        return LOCAL_AUTHORITY_DATA.get();
    }

    /**
     * 移除本地变量
     */
    public static void clearAuthorityData() {
        LOCAL_AUTHORITY_DATA.remove();
    }

    /**
     * 业务代码设置过滤条件
     *
     * @param type   数据行权限过滤类型
     * @param column SQL 中需要过滤的字段 如a.dept_id
     */
    public static void start(RowDataHandlerType type, String column) {
        DataRowAuthModel data = getLocalAuthorityData();
        if (data == null) {
            data = new DataRowAuthModel();
        }
        DataRowAuthColumn filterColumn = new DataRowAuthColumn(type, column);
        data.addFilterColumn(filterColumn);
        setLocalAuthorityData(data);
    }

    /**
     * 用处理后的SQL覆盖原始SQL
     *
     * 通过反射把SQL设置回去
     */
    public void overrideSql(BoundSql boundSql, String sql) {
        try {
            Field field = boundSql.getClass().getDeclaredField("sql");
            field.setAccessible(true);
            field.set(boundSql, sql);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
